#pragma once
#include <memory>
#include <functional>

#include "Socket.hpp"
#include "Protocol.hpp"

using namespace socket_ddsm;

class Factory
{
public:
    static std::shared_ptr<Request> BuildRequestDefault()
    {
        return std::make_shared<Request>();
    }
    static std::shared_ptr<Response> BuildResponseDefault()
    {
        return std::make_shared<Response>();
    }
};
class IOService
{
    // IOService只负责IO，不提供服务，需要上层传回调函数
    using process_t = std::function<std::shared_ptr<Response>(std::shared_ptr<Request>)>;

public:
    IOService(process_t process)
        :_process(process)
    {
    }

    void IOExcute(SockSPtr smsock, const Inet &addr)
    {
        // 长服务
        std::string packageStreamQueue;
        while (true)
        {
            // 在网络中读取，其实就是不断的在pageStreamQueue后面+=字符串
            ssize_t n = smsock->Recv(&packageStreamQueue);
            if (n <= 0)
            {
                LOG(INFO, "client [%s] quit/EOF OR read fail!\n", addr.UniqueName().c_str());
                break;
            }
            // 检查字节流是否有一个完整的报文
            std::string package = DeCode(packageStreamQueue);
            if (package.empty())
                continue;

            // 到这里，package 就是一个完整的报文
            auto req = Factory::BuildRequestDefault();

            // 反序列化
            req->Deserialize(package);

            // 业务处理
            auto resp = _process(req);

            std::string respjson;
            resp->Serialize(&respjson);

            respjson = EnCode(respjson);

            smsock->Send(respjson);
        }
    }

    ~IOService()
    {
    }

private:
    process_t _process;
};
